package com.chenfan.mcn.model.dto;

import cn.hutool.core.util.ArrayUtil;
import com.chenfan.common.dto.UserPrivilegeDTO;
import com.chenfan.mcn.config.UserVoContextHolder;
import com.chenfan.mcn.constant.NumberCst;
import com.chenfan.common.exception.BusinessException;
import com.chenfan.mcn.exception.McnErrorCode;
import com.chenfan.mcn.utils.CommonUtil;
import com.chenfan.privilege.common.constant.DataPrivilegeInfo;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.ReflectionUtils;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
import java.util.List;

/**
 * @author 2062
 */
@EqualsAndHashCode(callSuper = true)
@Data
@SuppressWarnings({"AlibabaPojoNoDefaultValue", "AlibabaAbstractClassShouldStartWithAbstractNaming","AlibabaRemoveCommentedCode"})
public abstract class AbstractMcnPrivilegeDTO<T> extends UserPrivilegeDTO implements Serializable {

    private static final long serialVersionUID = 8959384396583127719L;

    private List<Long> mainCustomerIds;

    private List<Long> viceCustomerIds;

    private List<Long> kaCustomerIds;

    private List<Long> noKaCustomerIds;

    /**
     * 查询时 使用别名
     */
    private String alias;

    /**
     * 0：升序，1：降序
     */
    private Integer order = NumberCst.ONE;

    /**
     * 字段
     */
    private String fieldName;

    /**
     * 是否开启
     */
    private Boolean enabled = true;

    public final String getAlias() {
        return StringUtils.defaultIfBlank(this.alias, "");
    }

    public String getFieldName() {
        if (StringUtils.isBlank(this.fieldName)) {
            this.fieldName = "updateDate";
        }
        Field field = getPrivilegeField(this, this.fieldName);
        if (field == null) {
            throw new BusinessException(McnErrorCode.ORDER_FEILD_NOT_EXIST);
        }
        this.setFieldName(field.getName());
        return StringUtils.defaultString(this.alias) + com.baomidou.mybatisplus.core.toolkit.StringUtils.camelToUnderline(this.fieldName)
                + (NumberCst.ZERO.equals(this.getOrder()) ? " asc" : " desc");
    }

    /**
     * 获取非KA客户
     *
     * @return
     */
    public final List<Long> getNoKaCustomerIds() {
        if (CollectionUtils.isNotEmpty(noKaCustomerIds) || CollectionUtils.isEmpty(mainCustomerIds)) {
            return noKaCustomerIds;
        }
        List<Long> noKaCustomerIds = new ArrayList<>(mainCustomerIds.size());
        noKaCustomerIds.addAll(mainCustomerIds);
        if (CollectionUtils.isNotEmpty(kaCustomerIds)) {
            noKaCustomerIds.removeAll(kaCustomerIds);
        }
        this.setNoKaCustomerIds(noKaCustomerIds);
        return this.noKaCustomerIds;
    }


    /**
     * 获取数据权限
     *
     * @return
     */
    public final String getDataPrivilege() {
        if(!enabled) {
            return null;
        }
        StringBuilder sb = new StringBuilder();
        //默认租户隔离
        //this.extendTenantPrivilege(sb);
        //如果配置相关数据权限，则进行扩展
        String[] dataScops = StringUtils.split(this.getDataPrivilegeCode(), ',');
        if (ArrayUtils.isNotEmpty(dataScops)) {
            this.extendDataPrivilege(sb, dataScops);
        } else {
            //如果未配置则查询不到数据 注：目前很多弹窗-取不到权限标识，暂无法开启
            //sb.append(" AND 1<>1 ");
        }
        return sb.toString();
    }

    /**
     * 数据权限扩展
     *
     * @param sb
     */
    protected void extendDataPrivilege(StringBuilder sb, String[] dataScops) {
        //公司或子公司-数据权限过滤
        if (CommonUtil.anyEqualsIgnoreCase(dataScops, DataPrivilegeInfo.COMPANY, DataPrivilegeInfo.SUB_COMPANY)) {
            this.extendCompanyPrivilege(sb);
            return;
        }
        //部门-数据权限过滤
        if (CommonUtil.anyEqualsIgnoreCase(dataScops, DataPrivilegeInfo.DEPARTMENT)) {
            this.extendDepartmentPrivilege(sb);
            this.joinCustomerAndUserPrivilege(sb);
            return;
        }
        //个人-数据权限过滤
        if (CommonUtil.anyEqualsIgnoreCase(dataScops, DataPrivilegeInfo.USER)) {
            this.joinCustomerAndUserPrivilege(sb);
            return;
        }
    }

    /**
     * 拼接客户与用户权限
     *
     * @param sb
     */
    private void joinCustomerAndUserPrivilege(StringBuilder sb) {
        StringBuilder customerSb = new StringBuilder();
        this.extendCustomerPrivilege(customerSb);
        if (customerSb.length() > 0) {
            sb.append(String.format(" AND (%s) ", customerSb.toString()));
        } else {
            this.extendUserPrivilege(sb);
        }
    }

    /**
     * 租户权限扩展
     *
     * @param sb
     */
    protected void extendTenantPrivilege(StringBuilder sb) {
        Long tenantId = ObjectUtils.defaultIfNull(this.getTenantId(), ObjectUtils.defaultIfNull(UserVoContextHolder.getTenantId(), -1L));
        sb.append(" AND " + this.getAlias() + "tenant_id = " + tenantId);
    }

    /**
     * 公司权限扩展
     *
     * @param sb
     */
    protected void extendCompanyPrivilege(StringBuilder sb) {
        if (CollectionUtils.isNotEmpty(this.getCompanyIds())) {
            sb.append(" AND ").append(this.getAlias()).append("company_id IN (").append(ArrayUtil.join(this.getCompanyIds().toArray(), ",")).append(")");
        } else {
            sb.append(" AND ").append(this.getAlias()).append("company_id = ").append(ObjectUtils.defaultIfNull(UserVoContextHolder.getCompanyId(), -1L));
        }
    }

    /**
     * 部门权限扩展
     *
     * @param sb
     */
    protected void extendDepartmentPrivilege(StringBuilder sb) {
        /** 目前用户存在组织机构调整，但数据记录的部门ID不会变更，不能对部门过滤 */
/*        if(CollectionUtils.isNotEmpty(this.getDepartmentIds())) {
            sb.append(" AND ").append(this.getAlias()).append("department_id IN ( ").append(ArrayUtil.join(this.getDepartmentIds().toArray(), ",")).append(" )");
        } else {
            sb.append(" AND ").append(this.getAlias()).append("department_id = ").append(ObjectUtils.defaultIfNull(UserVoContextHolder.getDepartmentId(),-1L));
        }*/
    }

    /**
     * 个人权限扩展
     *
     * @param sb
     */
    protected void extendUserPrivilege(StringBuilder sb) {
        if (CollectionUtils.isNotEmpty(this.getUserIds())) {
            sb.append(" AND ").append(this.getAlias()).append("owner_id IN ( ").append(ArrayUtil.join(this.getUserIds().toArray(), ",")).append(" )");
        } else {
            sb.append(" AND ").append(this.getAlias()).append("owner_id = ").append(ObjectUtils.defaultIfNull(UserVoContextHolder.getUserId(), -1L));
        }
    }

    /**
     * 品牌拓展
     *
     * @param sb
     */
    protected void extendBrandPrivilege(StringBuilder sb) {
        if (CollectionUtils.isNotEmpty(this.getBrandIds())) {
            sb.append(" AND ").append(this.getAlias()).append("brand_id IN ( ").append(ArrayUtil.join(this.getBrandIds().toArray(), ",")).append(" )");
        }
    }

    /**
     * 客户权限扩展
     *
     * @return
     */
    protected void extendCustomerPrivilege(StringBuilder sb) {
        Field field = getPrivilegeField(this, "customerId");
        if (field == null) {
            return;
        }
        if(CollectionUtils.isEmpty(this.kaCustomerIds) && CollectionUtils.isEmpty(this.mainCustomerIds) && CollectionUtils.isEmpty(this.viceCustomerIds) ) {
            return;
        }
        if (CollectionUtils.isNotEmpty(this.kaCustomerIds)) {
            sb.append(this.getAlias()).append("customer_id IN (").append(ArrayUtil.join(this.kaCustomerIds.toArray(), ",")).append(") ");
        }
        List<Long> targetCustomerIds = CommonUtil.getTargetList(this.getNoKaCustomerIds(), this.viceCustomerIds);
        if (CollectionUtils.isNotEmpty(targetCustomerIds)) {
            sb.append(CollectionUtils.isNotEmpty(this.kaCustomerIds) ? " OR (" : " (");
            sb.append(this.getAlias()).append("customer_id IN ( ").append(ArrayUtil.join(targetCustomerIds.toArray(), ",")).append(" )");
            if (CollectionUtils.isNotEmpty(this.getUserIds())) {
                sb.append(" AND ").append(this.getAlias()).append(" owner_id IN ( ").append(ArrayUtil.join(getUserIds().toArray(), ",")).append(" )");
            }
            sb.append(" )");
        }

        if (CollectionUtils.isNotEmpty(this.getUserIds())) {
            sb.append(sb.length() > 0 ? " OR (" : " (");
            sb.append(this.getAlias()).append(" owner_id IN ( ").append(ArrayUtil.join(getUserIds().toArray(), ",")).append(" )");
            sb.append(" )");
        }
    }

    /**
     * 获取列Field
     * @param privilegeDTO
     * @param fieldName
     * @param <T>
     * @return
     */
    private static <T> Field getPrivilegeField(AbstractMcnPrivilegeDTO<T> privilegeDTO, String fieldName) {
        Class<T> entityClass = (Class<T>) ((ParameterizedType)privilegeDTO.getClass().getGenericSuperclass()).getActualTypeArguments()[0];
        return ReflectionUtils.findField(entityClass, fieldName);
    }
}
